home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / gui.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  16.6 KB  |  676 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19.  
  20. #include <stdio.h>
  21. #include <stdarg.h>
  22. #include <crtdbg.h>
  23.  
  24. #include <windows.h>
  25. #include <commctrl.h>
  26. #include <commdlg.h>
  27.  
  28. #include "ClippingControl.h"
  29. #include "PositionControl.h"
  30. #include "VideoSource.h"
  31. #include "Error.h"
  32. #include "List.h"
  33. #include "VBitmap.h"
  34.  
  35. #include "gui.h"
  36. #include "resource.h"
  37.  
  38. #define MAX_STATUS_PARTS (8)
  39.  
  40. static COLORREF g_crCustomColors[16];
  41.  
  42. extern HINSTANCE g_hInst;
  43. extern HWND g_hWnd;
  44. extern HWND g_hwndJobs;
  45.  
  46. static HWND g_hwndDebugWindow=NULL;
  47.  
  48. static List2<ModelessDlgNode> g_listModelessDlgs;
  49.  
  50. int g_debugVal, g_debugVal2;
  51.  
  52. extern "C" ycblit(void *, void *);
  53.  
  54. ////////////////////////////////////////////////////////////////////////////
  55.  
  56. BOOL CALLBACK DebugDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  57.     switch(msg) {
  58.     case WM_INITDIALOG:
  59.         SetDlgItemInt(hdlg, IDC_EDIT, g_debugVal, FALSE);
  60.         SetDlgItemInt(hdlg, IDC_EDIT2, g_debugVal2, FALSE);
  61.         return TRUE;
  62.     case WM_COMMAND:
  63.         switch(LOWORD(wParam)) {
  64.         case IDC_EDIT:
  65.         case IDC_SPIN:
  66.             {
  67.                 BOOL f;
  68.                 int v;
  69.  
  70.                 v = GetDlgItemInt(hdlg, IDC_EDIT, &f, FALSE);
  71.  
  72.                 if (f)
  73.                     g_debugVal = v;
  74.             }
  75.             break;
  76.         case IDC_EDIT2:
  77.         case IDC_SPIN2:
  78.             {
  79.                 BOOL f;
  80.                 int v;
  81.  
  82.                 v = GetDlgItemInt(hdlg, IDC_EDIT2, &f, FALSE);
  83.  
  84.                 if (f)
  85.                     g_debugVal2 = v;
  86.             }
  87.             break;
  88.         case IDCANCEL:
  89.             DestroyWindow(hdlg);
  90.             break;
  91.         }
  92.         return TRUE;
  93.  
  94.     case WM_DESTROY:
  95.         g_hwndDebugWindow = NULL;
  96.         return TRUE;
  97.     }
  98.     return FALSE;
  99. }
  100.  
  101. void guiOpenDebug() {
  102.     if (!g_hwndDebugWindow)
  103.         g_hwndDebugWindow = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_DEBUGVAL), NULL, DebugDlgProc);
  104.     else if (GetKeyState(VK_CONTROL)<0) {
  105.         char *p = new char[16384+128];
  106.         static const struct {
  107.             BITMAPINFOHEADER bih;
  108.             unsigned long p[8];
  109.         } f={
  110.             {sizeof(BITMAPINFOHEADER),128,128,1,8,BI_RGB,128*128,0,0,0,0},
  111.             {
  112.                 0xffffff,
  113.                 0xf1f1f1,
  114.                 0xdfdfdf,
  115.                 0xc9c9c9,
  116.                 0xafafaf,
  117.                 0x919191,
  118.                 0x6d6d6d,
  119.                 0x404040,
  120.             }
  121.         };
  122.  
  123.         ycblit(p,0);
  124.  
  125.         HDC hdc = GetDC(g_hWnd);
  126.         SetDIBitsToDevice(hdc, 0, 0, 128, 128, 0, 0, 0, 128, p, (const BITMAPINFO *)&f.bih, DIB_RGB_COLORS);
  127.         ReleaseDC(g_hWnd, hdc);
  128.  
  129.         delete[] p;
  130.     }
  131. }
  132.  
  133. ////////////////////////////////////////////////////////////////////////////
  134.  
  135. void guiDlgMessageLoop(HWND hDlg) {
  136.     MSG msg;
  137.  
  138.     while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  139.         if (!IsWindow(hDlg) || !IsDialogMessage(hDlg, &msg)) {
  140.             TranslateMessage(&msg);
  141.             DispatchMessage(&msg);
  142.         }
  143.     }
  144. }
  145.  
  146. bool guiCheckDialogs(LPMSG pMsg) {
  147.     ModelessDlgNode *pmdn, *pmdn_next;
  148.  
  149.     if (g_hwndJobs && IsDialogMessage(g_hwndJobs, pMsg))
  150.         return true;
  151.  
  152.     if (g_hwndDebugWindow && IsDialogMessage(g_hwndDebugWindow, pMsg))
  153.         return true;
  154.  
  155.     pmdn = g_listModelessDlgs.AtHead();
  156.  
  157.     while(pmdn_next = pmdn->NextFromHead()) {
  158.         if (IsDialogMessage(pmdn->hdlg, pMsg))
  159.             return true;
  160.  
  161.         pmdn = pmdn_next;
  162.     }
  163.  
  164.     return false;
  165. }
  166.  
  167. void guiAddModelessDialog(ModelessDlgNode *pmdn) {
  168.     if (pmdn->hdlg)
  169.         g_listModelessDlgs.AddTail(pmdn);
  170. }
  171.  
  172. void guiRedoWindows(HWND hWnd) {
  173.     HWND hWndStatus = GetDlgItem(hWnd, IDC_STATUS_WINDOW);
  174.     HWND hWndPosition = GetDlgItem(hWnd, IDC_POSITION);
  175.     RECT rClient, rStatus, rPosition;
  176.     INT aWidth[MAX_STATUS_PARTS];
  177.     int nParts;
  178.  
  179.     GetClientRect(hWnd, &rClient);
  180.     GetWindowRect(hWndStatus, &rStatus);
  181.     GetWindowRect(hWndPosition, &rPosition);
  182.  
  183.     SetWindowPos(hWndPosition,
  184.                 NULL,
  185.                 rClient.left,
  186.                 rClient.bottom - (rStatus.bottom-rStatus.top) - (rPosition.bottom-rPosition.top),
  187.                 rClient.right-rClient.left,
  188.                 rPosition.bottom-rPosition.top,
  189.                 SWP_NOACTIVATE|SWP_NOZORDER);
  190.  
  191.     SetWindowPos(hWndStatus,
  192.                 NULL,
  193.                 rClient.left,
  194.                 rClient.bottom - (rStatus.bottom-rStatus.top),
  195.                 rClient.right-rClient.left,
  196.                 rStatus.bottom-rStatus.top,
  197.                 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCOPYBITS);
  198.  
  199.     if ((nParts = SendMessage(hWndStatus, SB_GETPARTS, 0, 0))>1) {
  200.         int i;
  201.         INT xCoord = (rStatus.right-rStatus.left) - (rStatus.bottom-rStatus.top);
  202.  
  203.         aWidth[nParts-2] = xCoord;
  204.  
  205.         for(i=nParts-3; i>=0; i--) {
  206.             xCoord -= 60;
  207.             aWidth[i] = xCoord;
  208.         }
  209.         aWidth[nParts-1] = -1;
  210.  
  211.         SendMessage(hWndStatus, SB_SETPARTS, nParts, (LPARAM)aWidth);
  212.     }
  213.  
  214. }
  215.  
  216. void guiSetStatus(char *format, int nPart, ...) {
  217.     char buf[256];
  218.     va_list val;
  219.  
  220.     va_start(val, nPart);
  221.     vsprintf(buf, format, val);
  222.     va_end(val);
  223.  
  224.     SendMessage(GetDlgItem(g_hWnd, IDC_STATUS_WINDOW), SB_SETTEXT, nPart, (LPARAM)buf);
  225. }
  226.  
  227. void guiSetTitle(HWND hWnd, UINT uID, ...) {
  228.     char buf1[256],buf2[256];
  229.     va_list val;
  230.  
  231.     LoadString(g_hInst, uID, buf1, sizeof buf1);
  232.  
  233.     va_start(val, uID);
  234.     vsprintf(buf2, buf1, val);
  235.     va_end(val);
  236.  
  237.     SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)buf2);
  238. }
  239.  
  240. void guiMenuHelp(HWND hwnd, WPARAM wParam, WPARAM part, UINT *iTranslator) {
  241.     HWND hwndStatus = GetDlgItem(hwnd, IDC_STATUS_WINDOW);
  242.     char msgbuf[256];
  243.  
  244.     if (!(HIWORD(wParam) & MF_POPUP) && !(HIWORD(wParam) & MF_SYSMENU)) {
  245.         UINT *idPtr = iTranslator;
  246.  
  247.         while(idPtr[0]) {
  248.             if (idPtr[0] == LOWORD(wParam)) {
  249.                 if (LoadString(g_hInst, idPtr[1], msgbuf, sizeof msgbuf)) {
  250.                     SendMessage(hwndStatus, SB_SETTEXT, part, (LPARAM)msgbuf);
  251.                     return;
  252.                 }
  253.             }
  254.             idPtr += 2;
  255.         }
  256.     }
  257.  
  258.     SendMessage(hwndStatus, SB_SETTEXT, part, (LPARAM)"");
  259. }
  260.  
  261. void guiOffsetDlgItem(HWND hdlg, UINT id, LONG xDelta, LONG yDelta) {
  262.     HWND hwndItem;
  263.     RECT r;
  264.  
  265.     hwndItem = GetDlgItem(hdlg, id);
  266.     GetWindowRect(hwndItem, &r);
  267.     ScreenToClient(hdlg, (LPPOINT)&r);
  268.     SetWindowPos(hwndItem, NULL, r.left + xDelta, r.top + yDelta, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
  269. }
  270.  
  271. void guiResizeDlgItem(HWND hdlg, UINT id, LONG x, LONG y, LONG dx, LONG dy) {
  272.     HWND hwndItem;
  273.     DWORD dwFlags = SWP_NOACTIVATE|SWP_NOZORDER;
  274.     RECT r;
  275.  
  276.     if (!(x|y))
  277.         dwFlags |= SWP_NOMOVE;
  278.  
  279.     if (!(dx|dy))
  280.         dwFlags |= SWP_NOSIZE;
  281.  
  282.     hwndItem = GetDlgItem(hdlg, id);
  283.     GetWindowRect(hwndItem, &r);
  284.     ScreenToClient(hdlg, (LPPOINT)&r);
  285.     ScreenToClient(hdlg, (LPPOINT)&r + 1);
  286.     SetWindowPos(hwndItem, NULL,
  287.                 r.left + x,
  288.                 r.top + y,
  289.                 r.right - r.left + dx,
  290.                 r.bottom - r.top + dy,
  291.                 dwFlags);
  292. }
  293.  
  294. void guiSubclassWindow(HWND hwnd, WNDPROC newproc) {
  295.     SetWindowLong(hwnd, GWL_USERDATA, GetWindowLong(hwnd, GWL_WNDPROC));
  296.     SetWindowLong(hwnd, GWL_WNDPROC, (LPARAM)newproc);
  297. }
  298.  
  299. ///////////////////////////////////////
  300.  
  301. extern VideoSource *inputVideoAVI;
  302.  
  303. void guiPositionInitFromStream(HWND hWndPosition) {
  304.     if (!inputVideoAVI) return;
  305.  
  306.     SendMessage(hWndPosition, PCM_SETRANGEMIN, (BOOL)FALSE, inputVideoAVI->lSampleFirst);
  307.     SendMessage(hWndPosition, PCM_SETRANGEMAX, (BOOL)TRUE , inputVideoAVI->lSampleLast);
  308.     SendMessage(hWndPosition, PCM_SETFRAMERATE, 0, MulDiv(1000000, inputVideoAVI->streamInfo.dwScale, inputVideoAVI->streamInfo.dwRate));
  309. }
  310.  
  311. LONG guiPositionHandleCommand(WPARAM wParam, LPARAM lParam) {
  312.     if (!inputVideoAVI) return -1;
  313.  
  314.     switch(HIWORD(wParam)) {
  315.         case PCN_START:
  316.             SendMessage((HWND)lParam, PCM_SETPOS, (WPARAM)TRUE, inputVideoAVI->lSampleFirst);
  317.             return inputVideoAVI->lSampleFirst;
  318.         case PCN_BACKWARD:
  319.             {
  320.                 LONG lSample = SendMessage((HWND)lParam, PCM_GETPOS, 0, 0);
  321.  
  322.                 if (lSample > inputVideoAVI->lSampleFirst) {
  323.                     SendMessage((HWND)lParam, PCM_SETPOS, (WPARAM)TRUE, lSample-1);
  324.                     return lSample-1;
  325.                 }
  326.             }
  327.             break;
  328.         case PCN_FORWARD:
  329.             {
  330.                 LONG lSample = SendMessage((HWND)lParam, PCM_GETPOS, 0, 0);
  331.  
  332.                 if (lSample < inputVideoAVI->lSampleLast) {
  333.                     SendMessage((HWND)lParam, PCM_SETPOS, (WPARAM)TRUE, lSample+1);
  334.                     return lSample+1;
  335.                 }
  336.             }
  337.             break;
  338.         case PCN_END:
  339.             SendMessage((HWND)lParam, PCM_SETPOS, (WPARAM)TRUE, inputVideoAVI->lSampleLast);
  340.             return inputVideoAVI->lSampleLast;
  341.             break;
  342.  
  343.         case PCN_KEYPREV:
  344.             {
  345.                 LONG lSample = inputVideoAVI->prevKey(SendMessage((HWND)lParam, PCM_GETPOS, 0, 0));
  346.  
  347.                 if (lSample < 0) lSample = inputVideoAVI->lSampleFirst;
  348.  
  349.                 SendMessage((HWND)lParam, PCM_SETPOS, (WPARAM)TRUE, lSample);
  350.                 return lSample;
  351.             }
  352.             break;
  353.         case PCN_KEYNEXT:
  354.             {
  355.                 LONG lSample = inputVideoAVI->nextKey(SendMessage((HWND)lParam, PCM_GETPOS, 0, 0));
  356.  
  357.                 if (lSample < 0) lSample = inputVideoAVI->lSampleLast;
  358.  
  359.                 SendMessage((HWND)lParam, PCM_SETPOS, (WPARAM)TRUE, lSample);
  360.                 return lSample;
  361.             }
  362.             break;
  363.     }
  364.  
  365.     return -1;
  366. }
  367.  
  368. LONG guiPositionHandleNotify(WPARAM wParam, LPARAM lParam) {
  369.     LPNMHDR nmh = (LPNMHDR)lParam;
  370.     LONG pos;
  371.  
  372.     switch(nmh->code) {
  373.     case PCN_THUMBTRACK:
  374.     case PCN_THUMBPOSITION:
  375.     case PCN_PAGELEFT:
  376.     case PCN_PAGERIGHT:
  377.     case CCN_REFRESHFRAME:
  378.         pos = SendMessage(nmh->hwndFrom, PCM_GETPOS, 0, 0);
  379.  
  380.         if (inputVideoAVI) return pos;
  381.  
  382.         break;
  383.     }
  384.  
  385.     return -1;
  386. }
  387.  
  388. void guiPositionBlit(HWND hWndClipping, LONG lFrame, int w, int h) {
  389.     if (lFrame<0) return;
  390.     try {
  391.         BITMAPINFOHEADER *dcf;
  392.  
  393.         dcf = inputVideoAVI->getDecompressedFormat();
  394.  
  395.         if (lFrame < inputVideoAVI->lSampleFirst || lFrame >= inputVideoAVI->lSampleLast)
  396.             SendMessage(hWndClipping, CCM_BLITFRAME, (WPARAM)NULL, (LPARAM)NULL);
  397.       else {
  398.          Pixel32 *tmpmem;
  399.          void *pFrame = inputVideoAVI->getFrame(lFrame);
  400.  
  401.          if (w>0 && h>0 && (tmpmem = new Pixel32[((w+1)&~1)*h])) {
  402.             VBitmap vbt(tmpmem, w, h, 32);
  403.             BITMAPINFOHEADER bih;
  404.  
  405.             vbt.StretchBltBilinearFast(0, 0, w, h, &VBitmap(pFrame, dcf), 0, 0, dcf->biWidth, dcf->biHeight);
  406.             vbt.MakeBitmapHeader(&bih);
  407.  
  408.                SendMessage(hWndClipping, CCM_BLITFRAME, (WPARAM)&bih, (LPARAM)tmpmem);
  409.  
  410.             delete[] tmpmem;
  411.          } else
  412.                SendMessage(hWndClipping, CCM_BLITFRAME, (WPARAM)dcf, (LPARAM)pFrame);
  413.       }
  414.  
  415.     } catch(MyError e) {
  416.         _RPT0(0,"Exception!!!\n");
  417.     }
  418. }
  419.  
  420. bool guiChooseColor(HWND hwnd, COLORREF& rgbOld) {
  421.     CHOOSECOLOR cc;                 // common dialog box structure 
  422.  
  423.     // Initialize CHOOSECOLOR
  424.     memset(&cc, 0, sizeof(CHOOSECOLOR));
  425.     cc.lStructSize    = sizeof(CHOOSECOLOR);
  426.     cc.hwndOwner    = hwnd;
  427.     cc.lpCustColors    = (LPDWORD)g_crCustomColors;
  428.     cc.rgbResult    = rgbOld;
  429.     cc.Flags        = CC_FULLOPEN | CC_RGBINIT;
  430.  
  431.     if (ChooseColor(&cc)==TRUE) {;
  432.         rgbOld = cc.rgbResult;
  433.         return true;
  434.     }
  435.  
  436.     return false;
  437. }
  438.  
  439. ///////////////////////////////////////////////////////////////////////////
  440.  
  441. struct reposInitData {
  442.     struct ReposItem *lpri;
  443.     POINT *lppt;
  444.     HWND hwndParent;
  445.     RECT rParent;
  446.     HDWP hdwp;
  447. };
  448.  
  449. static BOOL CALLBACK ReposInitFunc(HWND hwnd, LPARAM lParam) {
  450.     const struct reposInitData *rid = (struct reposInitData *)lParam;
  451.     const struct ReposItem *lpri = rid->lpri;
  452.     POINT *lppt = rid->lppt;
  453.     UINT uiID = GetWindowLong(hwnd, GWL_ID);
  454.     RECT rc;
  455.  
  456.     while(lpri->uiCtlID) {
  457.         if (lpri->uiCtlID == uiID) {
  458.             GetWindowRect(hwnd, &rc);
  459.             ScreenToClient(rid->hwndParent, (POINT *)&rc + 0);
  460.             ScreenToClient(rid->hwndParent, (POINT *)&rc + 1);
  461.  
  462.             if (lpri->fReposOpts & REPOS_MOVERIGHT)
  463.                 lppt->x = rid->rParent.right - rc.left;
  464.  
  465.             if (lpri->fReposOpts & REPOS_MOVEDOWN)
  466.                 lppt->y = rid->rParent.bottom - rc.top;
  467.  
  468.             if (lpri->fReposOpts & REPOS_SIZERIGHT)
  469.                 lppt->x = rid->rParent.right - (rc.right-rc.left);
  470.  
  471.             if (lpri->fReposOpts & REPOS_SIZEDOWN)
  472.                 lppt->y = rid->rParent.bottom - (rc.bottom-rc.top);
  473.  
  474.             return TRUE;
  475.         }
  476.  
  477.         ++lpri, ++lppt;
  478.     }
  479.  
  480.     return TRUE;
  481. }
  482.  
  483. void guiReposInit(HWND hwnd, struct ReposItem *lpri, POINT *lppt) {
  484.     struct reposInitData rid;
  485.  
  486.     rid.lpri = lpri;
  487.     rid.lppt = lppt;
  488.     rid.hwndParent = hwnd;
  489.     GetClientRect(hwnd, &rid.rParent);
  490.  
  491.     EnumChildWindows(hwnd, ReposInitFunc, (LPARAM)&rid);
  492. }
  493.  
  494. static BOOL CALLBACK ReposResizeFunc(HWND hwnd, LPARAM lParam) {
  495.     const struct reposInitData *rid = (struct reposInitData *)lParam;
  496.     const struct ReposItem *lpri = rid->lpri;
  497.     POINT *lppt = rid->lppt;
  498.     UINT uiID = GetWindowLong(hwnd, GWL_ID);
  499.     RECT rc;
  500.  
  501.     while(lpri->uiCtlID) {
  502.         if (lpri->uiCtlID == uiID) {
  503.             UINT uiFlags;
  504.  
  505.             GetWindowRect(hwnd, &rc);
  506.             ScreenToClient(rid->hwndParent, (POINT *)&rc + 0);
  507.             ScreenToClient(rid->hwndParent, (POINT *)&rc + 1);
  508.  
  509.             if (lpri->fReposOpts & REPOS_MOVERIGHT) {
  510.                 rc.right -= rc.left;
  511.                 rc.left = rid->rParent.right - lppt->x;
  512.                 rc.right += rc.left;
  513.             }
  514.  
  515.             if (lpri->fReposOpts & REPOS_MOVEDOWN) {
  516.                 rc.bottom -= rc.top;
  517.                 rc.top = rid->rParent.bottom - lppt->y;
  518.                 rc.bottom += rc.top;
  519.             }
  520.  
  521.             if (lpri->fReposOpts & REPOS_SIZERIGHT)
  522.                 rc.right = rc.left + rid->rParent.right - lppt->x;
  523.  
  524.             if (lpri->fReposOpts & REPOS_SIZEDOWN)
  525.                 rc.bottom = rc.top + rid->rParent.bottom - lppt->y;
  526.  
  527.             uiFlags = (lpri->fReposOpts & (REPOS_MOVERIGHT | REPOS_MOVEDOWN) ? 0 : SWP_NOMOVE)
  528.                      |(lpri->fReposOpts & (REPOS_SIZERIGHT | REPOS_SIZEDOWN) ? 0 : SWP_NOSIZE)
  529.                      |SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER;
  530.  
  531.             if (rid->hdwp)
  532.                 DeferWindowPos(rid->hdwp, hwnd, NULL, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, uiFlags);
  533.             else
  534.                 SetWindowPos(hwnd, NULL, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, uiFlags);
  535.  
  536.             return TRUE;
  537.         }
  538.  
  539.         ++lpri, ++lppt;
  540.     }
  541.  
  542.     return TRUE;
  543. }
  544.  
  545. void guiReposResize(HWND hwnd, struct ReposItem *lpri, POINT *lppt) {
  546.     struct reposInitData rid;
  547.     int iWindows = 0;
  548.  
  549.     rid.lpri = lpri;
  550.     rid.lppt = lppt;
  551.     rid.hwndParent = hwnd;
  552.     GetClientRect(hwnd, &rid.rParent);
  553.  
  554.     while(lpri++->uiCtlID)
  555.         ++iWindows;
  556.  
  557.     rid.hdwp = BeginDeferWindowPos(iWindows);
  558.  
  559.     EnumChildWindows(hwnd, ReposResizeFunc, (LPARAM)&rid);
  560.  
  561.     EndDeferWindowPos(rid.hdwp);
  562. }
  563.  
  564. void guiDeferWindowPos(HDWP hdwp, HWND hwnd, HWND hwndInsertAfter, int x, int y, int dx, int dy, UINT flags) {
  565.     if (hdwp)
  566.         DeferWindowPos(hdwp, hwnd, hwndInsertAfter, x, y, dx, dy, flags);
  567.     else
  568.         SetWindowPos(hwnd, hwndInsertAfter, x, y, dx, dy, flags);
  569. }
  570.  
  571. void guiEndDeferWindowPos(HDWP hdwp) {
  572.     if (hdwp)
  573.         EndDeferWindowPos(hdwp);
  574. }
  575.  
  576. int guiMessageBoxF(HWND hwnd, LPCTSTR lpCaption, UINT uType, const char *format, ...) {
  577.     char buf[1024];
  578.     va_list val;
  579.  
  580.     va_start(val,format);
  581.     vsprintf(buf, format, val);
  582.     va_end(val);
  583.  
  584.     return MessageBox(hwnd, buf, lpCaption, uType);
  585. }
  586.  
  587. ///////////////////////////////////////////////////////////////////////////
  588.  
  589. void ticks_to_str(char *dst, DWORD ticks) {
  590.     int sec, min, hr, day;
  591.  
  592.     ticks /= 1000;
  593.     sec    = ticks %  60; ticks /=  60;
  594.     min    = ticks %  60; ticks /=  60;
  595.     hr    = ticks %  24; ticks /=  24;
  596.     day    = ticks;
  597.  
  598.     if (day)
  599.         wsprintf(dst,"%d:%02d:%02d:%02d",day,hr,min,sec);
  600.     else if (hr)
  601.         wsprintf(dst,"%d:%02d:%02d",hr,min,sec);
  602.     else
  603.         wsprintf(dst,"%d:%02d",min,sec);
  604. }
  605.  
  606. void size_to_str(char *dst, __int64 i64Bytes) {
  607.     if (i64Bytes < 65536) {
  608.         sprintf(dst, "%lu bytes", (unsigned long)i64Bytes);
  609.     } else if (i64Bytes < (1L<<24)) {
  610.         sprintf(dst, "%luK", (unsigned long)((i64Bytes+512) / 1024));
  611.     } else if ((unsigned long)i64Bytes == i64Bytes) {
  612.         i64Bytes += 52429;
  613.  
  614.         sprintf(dst, "%lu.%cMb", (unsigned long)(i64Bytes >> 20), (char)('0' + (( ((unsigned long)i64Bytes & 1048575) * 10)>>20)));
  615.     } else {
  616.         i64Bytes += (long)((1L<<30) / 200);
  617.  
  618.         sprintf(dst, "%I64u.%02dGb",
  619.                 i64Bytes>>30,
  620.                 (int)(
  621.                     (
  622.                         (
  623.                             (i64Bytes >> 10) & 1048575
  624.                         )*100
  625.                     ) >> 20
  626.                 )
  627.         );
  628.     }
  629. }
  630.  
  631.  
  632.  
  633.  
  634. int guiListboxInsertSortedString(HWND hwnd, const char *pszStr) {
  635.     int idx, cnt;
  636.     char buf[2048];
  637.     char *activebuf = buf, *activebufalloc = NULL;
  638.     int activebuflen = sizeof buf;
  639.  
  640.     cnt = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
  641.  
  642.     if (cnt==LB_ERR)
  643.         return -1;
  644.  
  645.     for(idx=0; idx<cnt; idx++) {
  646.         int len = SendMessage(hwnd, LB_GETTEXTLEN, idx, 0);
  647.  
  648.         if (len < 0) {
  649.             freemem(activebufalloc);
  650.             return -1;
  651.         }
  652.  
  653.         if (++len > activebuflen) {
  654.             activebuf = (char *)reallocmem(activebufalloc, len);
  655.  
  656.             if (!activebuf) {
  657.                 freemem(activebufalloc);
  658.                 return -1;
  659.             }
  660.  
  661.             activebufalloc = activebuf;
  662.             activebuflen = len;
  663.         }
  664.  
  665.         SendMessage(hwnd, LB_GETTEXT, idx, (LPARAM)activebuf);
  666.  
  667.         if (stricmp(pszStr, activebuf) < 0)
  668.             break;
  669.     }
  670.  
  671.     if (idx >= cnt)
  672.         idx = -1;
  673.  
  674.     return SendMessage(hwnd, LB_INSERTSTRING, idx, (LPARAM)pszStr);
  675. }
  676.